package com.zxl.study.support;


import com.alibaba.druid.pool.DruidPooledConnection;
import com.zxl.study.entities.MetaDatabase;
import com.zxl.study.entities.MetaTable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class ClientContext<T> {
    /**
     * 数据库策略集合<数据库类型, 数据库策略类>
     */
    private static Map<String, Class> STRATEGYS = new HashMap<>();

    static {
        STRATEGYS.put("Postgres", PostgresStrategy.class);
    }

    Strategy<T> strategy;

    public ClientContext() {
    }

    public ClientContext(Strategy<T> strategy) {
        this.strategy = strategy;
    }
    private Strategy<DruidPooledConnection> getStartegy(String databaseType) {
        Strategy<DruidPooledConnection> strategy = null;
        try {
            Class clazz = STRATEGYS.get(databaseType);
            if (clazz != null && (Strategy.class.isAssignableFrom(clazz))) {
                strategy = (Strategy<DruidPooledConnection>) clazz.newInstance();
            }
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return strategy;
    }


    public List<MetaTable> getRemoteTables(MetaDatabase database) {
        List<MetaTable> tableList;
        Connection conn = null;
        try {
            //根据表的信息获取数据库的信息
            String databaseType = database.getType();
            //存放查询表数据的数据
            Strategy strategy = getStartegy(databaseType);
            if (strategy == null) {
                return null;
            }
            ClientContext<DruidPooledConnection> context = new ClientContext<>(strategy);
            conn = getConnection(database);
            tableList = context.strategy.syncGetRemoteTables(conn, database, true, true);
        } finally {
            JdbcUtil.close(conn);
        }
        return tableList;
    }

    public Connection getConnection(MetaDatabase database) {
        Connection conn = null;
        try {
            ClientContext<DruidPooledConnection> context = getClientContext(database.getType());
            if (context != null) {
                conn = JdbcUtil.getConnection(database, context.strategy);
            }
        } finally {
            if (conn == null) {
                //获取数据库连接失败
                throw new RuntimeException("异常");
            }
        }
        return conn;
    }

    private ClientContext<DruidPooledConnection> getClientContext(String databaseType) {
        ClientContext<DruidPooledConnection> cc = null;
        try {
            Strategy<DruidPooledConnection> strategy = getStartegy(databaseType);
            if (strategy != null) {
                cc = new ClientContext<>(strategy);
            }
        } finally {
            if (cc == null) {
                throw new RuntimeException("异常");            }
        }
        return cc;
    }

}
